<template>
  <div class="right-container">
    <my-dialog
      title="添加权限"
      :modelValue="data.addDialogVisible"
      @update:modelValue="(val:any) => (data.addDialogVisible = val)"
      @confirm="events.handleAddRight"
    >
      <el-form ref="addFormRef" label-width="80px" :model="data.addForm">
        <el-form-item label="上级权限">
          <el-tag>{{ data.currentNode?.name }}</el-tag>
        </el-form-item>
        <el-form-item
          label="名称"
          prop="name"
          :rules="[{ required: true, message: '请填写名称' }]"
        >
          <el-input
            maxlength="100"
            v-model="data.addForm.name"
            placeholder="请输入名称"
            type="text"
            autocomplete="off"
          ></el-input>
        </el-form-item>
        <el-form-item
          label="URL"
          prop="url"
          :rules="[{ required: true, message: '请填写URL' },{
            validator: (rule: any, value: string) => {
              return /^((\/[a-zA-Z0-9-_\.]+)+|(\/))$/.test(value);
            },
            message: '请输入正确的URL格式，如/user/list'
          }]"
        >
          <el-input
            maxlength="500"
            :rows="2"
            v-model="data.addForm.url"
            placeholder="请输入URL"
            type="textarea"
            autocomplete="off"
          ></el-input>
        </el-form-item>
        <el-form-item
          label="菜单"
          prop="hasMenu"
          :rules="[{ required: true, message: '请选择是或否显示在菜单中' }]"
        >
          <el-radio-group v-model="data.addForm.hasMenu">
            <el-radio :value="1" border>显示在菜单中</el-radio>
            <el-radio :value="0" border>不显示在菜单中</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
    </my-dialog>
    <my-dialog
      title="修改权限"
      :modelValue="data.updateDialogVisible"
      @update:modelValue="(val:any) => (data.updateDialogVisible = val)"
      @confirm="events.handleUpdateRight"
    >
      <el-form ref="updateFormRef" label-width="80px" :model="data.updateForm">
        <el-form-item
          label="名称"
          prop="name"
          :rules="[{ required: true, message: '请填写名称' }]"
        >
          <el-input
            maxlength="100"
            v-model="data.updateForm.name"
            placeholder="请输入名称"
            type="text"
            autocomplete="off"
          ></el-input>
        </el-form-item>
        <el-form-item
          label="URL"
          prop="url"
          :rules="[{ required: true, message: '请填写URL' },{
            validator: (rule: any, value: string) => {
              return /^((\/[a-zA-Z0-9-_\.]+)+|(\/))$/.test(value);
            },
            message: '请输入正确的URL格式，如/user/list'
          }]"
        >
          <el-input
            maxlength="500"
            :rows="2"
            v-model="data.updateForm.url"
            placeholder="请输入URL"
            type="textarea"
            autocomplete="off"
          ></el-input>
        </el-form-item>
        <el-form-item
          label="菜单"
          prop="hasMenu"
          :rules="[{ required: true, message: '请选择是或否显示在菜单中' }]"
        >
          <el-radio-group v-model="data.updateForm.hasMenu">
            <el-radio :value="1" border>显示在菜单中</el-radio>
            <el-radio :value="0" border>不显示在菜单中</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
    </my-dialog>
    <el-scrollbar class="tree">
      <el-scrollbar class="tree-scrollbar">
        <el-tree
          :data="data.treeData"
          highlight-current
          default-expand-all
          :current-node-key="data.currentNodeKey"
          @node-click="events.handleNodeClick"
          :expand-on-click-node="false"
          node-key="id"
          :props="{ label: 'name', children: 'children' }"
        ></el-tree>
      </el-scrollbar>
      <div class="tree-add-box">
        <div>
          <el-button
            type="primary"
            size="small"
            class="block"
            @click="events.showAdd"
            >新增</el-button
          >
        </div>
      </div>
    </el-scrollbar>
    <div class="description">
      <el-descriptions :column="1" border label-width="20%">
        <template #title>
          <div class="description-header">
            <div class="description-title">权限详情</div>
          </div>
        </template>
        <template #extra>
          <div class="description-header">
            <template v-if="data.currentNode?.id">
              <el-popconfirm
                confirm-button-text="是"
                cancel-button-text="否"
                title="是否要删除该权限?"
                @confirm="events.handleDeleteRight"
              >
                <template #reference>
                  <el-button type="danger" plain>删除</el-button>
                </template>
              </el-popconfirm>
              <el-button type="warning" plain @click="events.showUpdate"
                >修改</el-button
              >
            </template>
          </div>
        </template>
        <el-descriptions-item label="编号" label-align="right">
          {{ data.currentNode?.id }}
        </el-descriptions-item>
        <el-descriptions-item label="名称" label-align="right">
          {{ data.currentNode?.name }}
        </el-descriptions-item>
        <el-descriptions-item label="URL" label-align="right">
          {{ data.currentNode?.url }}
        </el-descriptions-item>
        <el-descriptions-item label="是否禁用" label-align="right">
          <template v-if="data.currentNode">
            <el-tag
              size="small"
              :type="data.currentNode?.isBan == 1 ? 'danger' : 'success'"
              >{{ data.currentNode?.isBan == 1 ? '是' : '否' }}</el-tag
            >
          </template>
        </el-descriptions-item>
        <el-descriptions-item label="上级权限" label-align="right">
          {{ data.currentNode?.parentName }}
        </el-descriptions-item>
        <el-descriptions-item label="创建时间" label-align="right">
          {{
            data.currentNode
              ? new Date(data.currentNode?.createTime).toLocaleString()
              : ''
          }}
        </el-descriptions-item>
      </el-descriptions>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue';
import {
  addRight,
  deleteRight,
  getRightTree,
  updateRight,
} from '../../functions/right';
import MyDialog from '../../components/MyDialog.vue';
import { confirmBox, toast } from '../../utils/tools';

const addFormRef = ref<any>(null);
const updateFormRef = ref<any>(null);

interface Data {
  treeData: any[];
  currentNodeKey: number | null;
  currentNode: any;
  addDialogVisible: boolean;
  addForm: any;
  updateDialogVisible: boolean;
  updateForm: any;
}
const data = reactive<Data>({
  treeData: [],
  currentNodeKey: null,
  currentNode: null,
  addDialogVisible: false,
  addForm: {},
  updateDialogVisible: false,
  updateForm: {},
});
const methods = {
  bindTree: async () => {
    const res = await getRightTree();
    if (res.code >= 0) {
      data.treeData = res.data;
      if (data.currentNodeKey !== null) {
        data.currentNode = methods.findTreeNode(
          data.treeData,
          data.currentNodeKey
        );
      }
    }
  },
  resetAddForm: () => {
    addFormRef.value?.resetFields();
  },
  findTreeNode: (treeData: any[], id: number): any => {
    for (let i = 0; i < treeData.length; i++) {
      if (treeData[i].id === id) {
        return treeData[i];
      } else if (treeData[i].children) {
        const node = methods.findTreeNode(treeData[i].children, id);
        if (node) {
          return node;
        }
      }
    }
  },
};
const events = reactive({
  handleNodeClick: (d: any) => {
    if (data.currentNodeKey !== d.id) {
      data.currentNodeKey = d.id;
      data.currentNode = d;
    } else {
      data.currentNodeKey = null;
      data.currentNode = null;
    }
  },
  showAdd: () => {
    data.addDialogVisible = true;
  },
  showUpdate: () => {
    data.updateDialogVisible = true;
    data.updateForm = { ...data.currentNode };
  },
  handleUpdateRight: () => {
    updateFormRef.value?.validate(async (valid: any) => {
      if (valid) {
        // 验证成功，发送数据
        const res = await updateRight({
          ...data.updateForm,
          id: data.currentNode.id,
        });
        if (res.code >= 0) {
          data.updateDialogVisible = false;
          toast.success(res.message || '修改成功');
          await methods.bindTree();
        } else {
          toast.error(res.message || '修改失败');
        }
        return false;
      } else {
        console.log('表单验证失败!');
        return false;
      }
    });
  },
  handleDeleteRight: async () => {
    const res = await deleteRight(data.currentNode.id);
    if (res.code >= 0) {
      toast.success(res.message || '删除成功');
      await methods.bindTree();
    } else {
      toast.error(res.message || '删除失败');
    }
  },
  handleAddRight: async () => {
    addFormRef.value?.validate(async (valid: any) => {
      if (valid) {
        // 验证成功，发送数据
        if (data.currentNode?.id == null) {
          confirmBox('上级权限为空，是否确认添加？', async () => {
            const res = await addRight({
              ...data.addForm,
              parentId: data.currentNode?.id,
            });
            if (res.code >= 0) {
              data.addDialogVisible = false;
              methods.resetAddForm();
              toast.success(res.message || '添加成功');
              await methods.bindTree();
            } else {
              toast.error(res.message || '添加失败');
            }
          });
        } else {
          const res = await addRight({
            ...data.addForm,
            parentId: data.currentNode.id,
          });
          if (res.code >= 0) {
            data.addDialogVisible = false;
            methods.resetAddForm();
            toast.success(res.message || '添加成功');
            await methods.bindTree();
          } else {
            toast.error(res.message || '添加失败');
          }
        }
      } else {
        console.log('表单验证失败!');
        return false;
      }
    });
  },
});
onMounted(async () => {
  await methods.bindTree();
});
</script>

<style scoped lang="scss">
.right-container {
  height: 100%;
  display: flex;
}
.tree {
  width: 25%;
  height: 100%;
  overflow: auto;
  border-right: 1px solid #ccc;
}
.tree-scrollbar {
  height: 90%;
}
.tree-add-box {
  padding: 2%;
}
:deep(
    .el-tree--highlight-current
      .el-tree-node.is-current
      > .el-tree-node__content
  ) {
  background-color: #baf !important; /* 高亮背景色 */
  color: #fff; /* 字体颜色 */
  font-weight: bold; /* 字体加粗 */
}
.description {
  width: 75%;
  height: 100%;
}
.description-title {
  padding: 8px;
  font-weight: bold;
}
.description-header {
  padding-top: 10px;
  padding-right: 10px;
}
</style>
